import DictionaryAPI from '@/api/Dictionary';
import {
  Box,
  clearDictByCodes,
  FieldCols,
  FieldEffect,
  FormSection,
  mapField,
  useCall,
  useReq,
  useSimpleMemo,
} from '@/components';
import { DICTIONARY_BASE_ROUTE, rootIdProps } from '@/pages/data/Dictionary/components/shared';
import { pathJoin } from '@/utils';
import { catchAndScrollFor } from '@/utils/fp';
import { Button, Divider, Form, Space, Spin } from 'antd';
import * as PropTypes from 'prop-types';
import React, { createContext, useContext, useEffect } from 'react';
import { Link, useHistory } from 'react-router-dom';
import DictionaryTable from './DictionaryTable';

const Context = createContext({ type: null, id: null });

const FIELDS = [
  ['code', '字典代码', null, { required: true }],
  ['cnName', '中文名称', null, { required: true }],
  ['enName', '英文名称'],
  ['value', '字典值'],
  [
    'parentId',
    '父级字典',
    'select',
    {
      initialValue: '0',
      getValueProps: (v) => ({ value: sessionStorage.getItem(`DICT_NAME:${v}`) || v }),
      ...rootIdProps,
      getFieldProps(item, index, form) {
        const ret = rootIdProps?.getFieldProps?.(...arguments) ?? null;
        const ctx = useContext(Context);
        const isAddChild = ctx.type === 'add' && ctx.id;

        return {
          ...ret,
          options: [{ value: '0', label: '无' }, ...ret?.options],
          disabled: isAddChild,
        };
      },
    },
  ],
  ['sort', '排序', 'input-number'],
  [
    'enabled',
    '是否启用',
    'radio-group',
    {
      initialValue: '1',
      options: [
        { value: '1', label: '是' },
        { value: '0', label: '否' },
      ],
    },
  ],
].map(mapField);

const ChildDict = ({ id }) => {
  return (
    <DictionaryTable
      serviceData={[
        {
          t: {
            parentId: id,
          },
        },
      ]}
    />
  );
};

function DictionaryForm(props) {
  const history = useHistory();
  const [form] = Form.useForm();
  const { type, id } = props;
  const xhr = useReq(DictionaryAPI.getById);
  const saveXhr = useReq(DictionaryAPI.insert);
  const updateXhr = useReq(DictionaryAPI.update);

  const loading = [xhr.status, saveXhr.status, updateXhr.status].includes('loading');

  useEffect(() => {
    if (type === 'edit' && id) xhr.start(id);
  }, [type, id]);

  useEffect(() => {
    form.setFieldsValue(xhr.result);
  }, [xhr.result]);

  useEffect(() => {
    if (type === 'add' && id && form.getFieldValue('parentId') !== id) {
      form.setFieldsValue({ parentId: id });
    }
  }, [id]);

  const handleSave = useCall(async () => {
    const data = await form.validateFields().catch(catchAndScrollFor(form));
    await (type === 'edit' ? updateXhr : saveXhr).start(data);
    if (type === 'add') history.goBack();
    clearDictByCodes();
  });

  const parentId = xhr.result?.parentId ?? '0';

  return (
    <Spin spinning={loading}>
      <Form form={form}>
        <FieldEffect name='id' />
        <FormSection
          title={
            <Box component={Space} flex dir='row' ali='center'>
              <span>字典配置</span>
              {parentId !== '0' && (
                <Link to={pathJoin(DICTIONARY_BASE_ROUTE, 'edit', { id: parentId })}>
                  <Button type='link' size='middle'>
                    查看父级
                  </Button>
                </Link>
              )}
            </Box>
          }
        >
          <FieldCols form={form} fields={FIELDS} />

          <Box flex jus='end' py={2} px={2}>
            <Space size='large'>
              <Button onClick={history.goBack}>返回</Button>
              <Button onClick={handleSave} type='primary'>
                保存
              </Button>
            </Space>
          </Box>
        </FormSection>
      </Form>
    </Spin>
  );
}

function EditDictionary({ id, type }) {
  const context = useSimpleMemo({ id, type });

  return (
    <Context.Provider value={context}>
      <DictionaryForm id={id} type={type} />
      {type === 'edit' && (
        <>
          <Divider />
          <FormSection
            title='子字典'
            right={
              <Link to={pathJoin('add', { id })}>
                <Button>新增子字典</Button>
              </Link>
            }
          >
            <ChildDict id={id} />
          </FormSection>
        </>
      )}
    </Context.Provider>
  );
}

EditDictionary.propTypes = {
  type: PropTypes.oneOf(['add', 'edit', 'view']),
  id: PropTypes.any,
};

export default EditDictionary;
